﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace HerbertDotNet.Visualizer
{
    public class WebHelper
    {
        public static event EventHandler<CheckForUpdatesCompletedEventArgs> CheckForUpdatesCompleted;

        public static void CheckForUpdatesAsync(string url)
        {
            var webClient = new WebClient();

            // Download HTML from specified URL asynchronously.
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(
                CheckForUpdatesCallback);
            webClient.DownloadStringAsync(new Uri(url));
        }

        public static void CheckForUpdates(string url)
        {
            var webClient = new WebClient();

            try
            {
                // Download HTML from specified URL.
                var result = webClient.DownloadString(url);

                // Interpret update page.
                InterpretUpdatePage(result);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error checking project website for updates.\r\n\r\n" + ex.Message,
                    Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                webClient.Dispose();
            }
        }

        protected static void CheckForUpdatesCallback(object sender, DownloadStringCompletedEventArgs e)
        {
            WebClient webClient = (WebClient)sender;
            
            try
            {
                if (e.Cancelled) return;
                if (e.Error != null) throw e.Error;
                
                InterpretUpdatePage(e.Result);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error checking project website for updates.\r\n\r\n" + ex.Message,
                    Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                webClient.Dispose();
            }
        }

        public static void LaunchUrl(string url)
        {
            try
            {
                // Start default process for specified URL.
                Process.Start(url);
            }
            catch (System.ComponentModel.Win32Exception exWin32)
            {
                MessageBox.Show("The application could not launch the web page because an error occurred."
                    + "\r\n\r\n" + exWin32.Message,
                    Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        protected static void InterpretUpdatePage(string pageContent)
        {
            // Find link URL and text for each release.
            var pageText = pageContent;
            Regex currentReleaseRegex = new Regex("<a id=\"ctl00_.*releaseLink\" href=\"(?<url>.*)\">"
                + "(?<text>.*)</a>", RegexOptions.IgnoreCase);
            var matches = currentReleaseRegex.Match(pageText);
            var releaseUrl = matches.Groups["url"].Value;
            var releaseText = matches.Groups["text"].Value;

            // Raise event: check for updates has completed.
            var releaseVersion = new Version(releaseText.Substring(releaseText.LastIndexOf("v") + 1));

            if (CheckForUpdatesCompleted != null) 
                CheckForUpdatesCompleted(null, new CheckForUpdatesCompletedEventArgs(releaseText, 
                    releaseUrl, releaseVersion));
        }
    }

    public class CheckForUpdatesCompletedEventArgs : EventArgs
    {
        public CheckForUpdatesCompletedEventArgs(string latestReleaseText, string latestReleaseUrl,
            Version latestReleaseVersion) : base()
        {
            this.LatestReleaseText = latestReleaseText;
            this.LatestReleaseUrl = latestReleaseUrl;
            this.LatestReleaseVersion = latestReleaseVersion;
        }

        public Version LatestReleaseVersion
        {
            get;
            protected set;
        }

        public string LatestReleaseText
        {
            get;
            protected set;
        }

        public string LatestReleaseUrl
        {
            get;
            protected set;
        }
    }
}
